/******************************************************************************
 * Copyright (c) 20203, Freqchip
 *
 * All rights reserved.
 *
 *
 */
#include <stdio.h>
#include <string.h>
//#include <core_cm33.h>

#include "fr30xx.h"
#include "co_util.h"
#include "gap_api.h"
#include "gatt_api.h"
#include "FreeRTOS.h"
#include "timers.h"

#include "ota.h"
#include "ota_service.h"

/******************************************************************************
 * MACROS (宏定义)
 */

/*****************************************************************************
 * CONSTANTS (常量定义)
 */
#define PMU_REG_FLASH_VDD_CTRL          0xFB
/*****************************************************************************
* TYPEDEFS (类型定义)
*/
__PACKED_STRUCT ota_ongoing_t{
    uint8_t  type;
    uint8_t  start_flag;
    uint8_t  erase_flag;
    uint8_t  mac_addr[6];
};
__PACKED_STRUCT ota_file_version_t{
    uint32_t otaboot_version;
    uint32_t app_version;
    uint32_t controller_version;
    uint32_t dsp_version;
};
__PACKED_STRUCT file_info_t{
    uint32_t file_version;
    uint32_t file_storage_base;
    uint32_t file_length;
    uint32_t file_crc;
};
__PACKED_STRUCT ota_info_t{
    uint8_t                   first_check_flag[4]; 
    uint8_t                   file_type;   //烧录文件中，所包含的文件类型
    struct file_info_t        boot_file_info;
    struct file_info_t        app_file_info;
    struct file_info_t        controller_file_info;
    struct file_info_t        dsp_file_info;
    uint8_t                   controller_flag;
    struct ota_ongoing_t      ota_ongoing;
    uint32_t rsv[10];
};

__PACKED_STRUCT firmware_version
{
    uint32_t firmware_version;
} __attribute__((packed));

__PACKED_STRUCT storage_baseaddr
{
    uint32_t baseaddr;
} __attribute__((packed));

__PACKED_STRUCT page_erase_rsp
{
    uint32_t base_address;
} __attribute__((packed));

__PACKED_STRUCT write_mem_rsp
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT read_mem_rsp
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT write_data_rsp
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT read_data_rsp
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT ota_start_rsp
{
    uint32_t ota_start;
} __attribute__((packed));

__PACKED_STRUCT ota_finish_rsp
{
    uint32_t ota_finsih_state;
} __attribute__((packed));

__PACKED_STRUCT app_ota_rsp_hdr_t
{
    uint8_t result;
    uint8_t org_opcode;
    uint16_t length;
    __PACKED union
    {
        uint8_t nvds_type;
        struct firmware_version version;
        struct storage_baseaddr baseaddr;
        struct page_erase_rsp page_erase;
        struct write_mem_rsp write_mem;
        struct read_mem_rsp read_mem;
        struct write_data_rsp write_data;
        struct read_data_rsp read_data;
        struct ota_finish_rsp finsih_rsp;
        struct ota_start_rsp ota_start;
    } __attribute__((packed)) rsp;
} __attribute__((packed));

__PACKED_STRUCT page_erase_cmd
{
    uint32_t base_address;
} __attribute__((packed));

__PACKED_STRUCT write_mem_cmd
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT read_mem_cmd
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT write_data_cmd
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT read_data_cmd
{
    uint32_t base_address;
    uint16_t length;
} __attribute__((packed));

__PACKED_STRUCT firmware_check
{
    uint32_t firmware_length;
    uint32_t CRC32_data;
} __attribute__((packed));
__PACKED_STRUCT  app_ota_cmd_hdr_t
{
    uint8_t opcode;
    uint16_t length;
    __PACKED union
    {
        struct page_erase_cmd page_erase;
        struct write_mem_cmd write_mem;
        struct read_mem_cmd read_mem;
        struct write_data_cmd write_data;
        struct read_data_cmd read_data;
        struct firmware_check fir_crc_data;
    } __attribute__((packed)) cmd;
} __attribute__((packed));

__PACKED_STRUCT otas_send_rsp
{
    uint8_t conidx;
    uint16_t length;
    uint8_t *buffer;
};
/******************************************************************************
 * LOCAL VARIABLES (局部变量)
 */
static struct ota_info_t  * ota_info;
/******************************************************************************
 * GLOBAL VARIABLES (全局变量)
 */
extern uint8_t ble_static_addr[6];
/******************************************************************************
 * LOCAL FUNCTIONS (本地函数)
 */

/******************************************************************************
 * EXTERN FUNCTIONS (外部函数)
 */
extern void wdt_rst_start(void);

void show_reg(uint8_t *buffer,uint16_t length)
{
    for(int i = 0; i < length; i++)
    {
        printf("%02x ",buffer[i]);
    }
    printf("\r\n");
}

void ota_check_file_init(void)
{
    ota_info = pvPortMalloc(sizeof(struct ota_info_t));
    flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info);
}

void ota_deinit(void)
{
    
}
/*********************************************************************
 * @fn      app_otas_recv_data
 *
 * @brief   Otas Data handler
 *
 */
void app_otas_recv_data(uint8_t conidx,uint8_t *p_data,uint16_t len)
{
    struct app_ota_cmd_hdr_t *cmd_hdr = (struct app_ota_cmd_hdr_t *)p_data;
    struct app_ota_rsp_hdr_t *rsp_hdr;
    uint16_t rsp_data_len = (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN);
    switch(cmd_hdr->opcode)
    {
        case OTA_CMD_NVDS_TYPE:
            rsp_data_len += 1;
            break;
        case OTA_CMD_GET_STR_BASE:
            rsp_data_len += sizeof(struct storage_baseaddr);
            break;
        case OTA_CMD_READ_FW_VER:
            rsp_data_len += sizeof(struct firmware_version);
            break;
        case OTA_CMD_PAGE_ERASE:
            rsp_data_len += sizeof(struct page_erase_rsp);
            break;
        case OTA_CMD_WRITE_DATA:
            rsp_data_len += sizeof(struct write_data_rsp);
            break;
        case OTA_CMD_READ_DATA:
            rsp_data_len += sizeof(struct read_data_rsp);
            break;
        case OTA_CMD_WRITE_MEM:
            rsp_data_len += sizeof(struct write_mem_rsp);
            break;
        case OTA_CMD_READ_MEM:
            rsp_data_len += sizeof(struct read_mem_rsp);
            break;
        case OTA_CMD_START:
            rsp_data_len += sizeof(struct ota_start_rsp);
            break;
        case OTA_CMD_NULL:
            
            return;
    }
    struct otas_send_rsp *req = pvPortMalloc(sizeof(struct otas_send_rsp));
    uint16_t base_length;
    req->conidx = conidx;
    req->length = rsp_data_len;
    req->buffer = pvPortMalloc(rsp_data_len);
    rsp_hdr = (struct app_ota_rsp_hdr_t *)&req->buffer[0];
    rsp_hdr->result = OTA_RSP_SUCCESS;
    rsp_hdr->org_opcode = cmd_hdr->opcode;
    rsp_hdr->length = rsp_data_len - (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN);
    
    switch(cmd_hdr->opcode)
    {
        case OTA_CMD_NVDS_TYPE:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_GET_STR_BASE:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_READ_FW_VER:
        {
            uint8_t type;
            type = *(p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN));
            switch(type)
            {
                case FILE_BOOT_LOADER:
                    rsp_hdr->rsp.version.firmware_version = ota_info->boot_file_info.file_version;
                break;
                
                case FILE_APP:
                    rsp_hdr->rsp.version.firmware_version = ota_info->app_file_info.file_version;
                break;
                
                case FILE_CONTROLLER:
                    rsp_hdr->rsp.version.firmware_version = ota_info->controller_file_info.file_version;
                break;
                case FILE_DSP:
                    rsp_hdr->rsp.version.firmware_version = ota_info->dsp_file_info.file_version;
                break;
            }
            printf("version:%x",rsp_hdr->rsp.version.firmware_version);
        }
            break;
        case OTA_CMD_PAGE_ERASE:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_CHIP_ERASE:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_WRITE_DATA:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_READ_DATA:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_WRITE_MEM:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_READ_MEM:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
        case OTA_CMD_REBOOT:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
       case OTA_CMD_START:
       {    
            uint8_t ota_type;
            ota_type = *(p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN));
            printf("ota type:%d\r\n",ota_type);
            ota_info->ota_ongoing.type = ota_type;

            ota_info->ota_ongoing.start_flag = 0x01;
            ota_info->ota_ongoing.erase_flag = 0;
            memcpy(ota_info->ota_ongoing.mac_addr,ble_static_addr,6);
            flash_erase(QSPI0,OTA_BOOT_INFO_ADDRESS,0x1000);
            flash_write(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info);
            wdt_rst_start();
            rsp_hdr->rsp.ota_start.ota_start = 0;
        }
            break;
        default:
            rsp_hdr->result = OTA_RSP_ERROR;
            break;
    }
    ota_gatt_report_notify(conidx,req->buffer,req->length);
    vPortFree(req->buffer);
    vPortFree(req);
}



